<?php
class LtUrl
{
    public $configHandle;
    public $routingTable;
    public $baseUrl;
    public function __construct()
    {
        if (!$this->configHandle instanceof LtConfig) {
            if (class_exists("LtObjectUtil", false)) {
                $this->configHandle = LtObjectUtil::singleton("LtConfig");
            } else {
                $this->configHandle = new LtConfig;
            }
        }
    }
    public function init()
    {
        $this->routingTable = $this->configHandle->get("router.routing_table");
        if (empty($this->routingTable)) {
            $this->routingTable = array(
                'pattern' => ":module/:action/*",
                'default' => array(
                    'module' => 'default',
                    'action' => 'index'
                ),
                'reqs' => array(
                    'module' => '[a-zA-Z0-9\.\-_]+',
                    'action' => '[a-zA-Z0-9\.\-_]+'
                ),
                'varprefix' => ':',
                'delimiter' => '/',
                'postfix' => '',
                'protocol' => 'PATH_INFO' // REWRITE STANDARD
            );
        }
        $protocol = strtoupper($this->routingTable['protocol']);
        if ('REWRITE' == $protocol) {
            $this->baseUrl = pathinfo($_SERVER['SCRIPT_NAME'], PATHINFO_DIRNAME) . '/';
        } else if ('STANDARD' == $protocol) {
            $this->baseUrl = $_SERVER['PHP_SELF'];
        } else {
            $this->baseUrl = '';
        }
    }
    public function generate($module, $action, $args = array())
    {
        $args = array_merge(array(
            'module' => $module,
            'action' => $action
        ), $args);
        $url  = '';
        // $url = $_SERVER['SERVER_PORT'] == '443' ? 'https://' : 'http://';
        // $url .= $_SERVER['HTTP_HOST'];
        // $url .= $_SERVER['SERVER_PORT'] == '80' ? '' : ':'.$_SERVER['SERVER_PORT'];
        $url .= $this->baseUrl;
        $url .= $this->reverseMatchingRoutingTable($args);
        return $url;
    }
    /**
     * 将变量反向匹配路由表, 返回匹配后的url
     * 
     * @param array $params 
     * @return string 
     */
    public function reverseMatchingRoutingTable($args)
    {
        $ret       = $this->routingTable['pattern'];
        $default   = $this->routingTable['default'];
        $reqs      = $this->routingTable['reqs'];
        $delimiter = $this->routingTable['delimiter'];
        $varprefix = $this->routingTable['varprefix'];
        $postfix   = $this->routingTable['postfix'];
        $protocol  = strtoupper($this->routingTable['protocol']);
        if ('STANDARD' == $protocol) {
            return '?' . http_build_query($args, '', '&');
        }
        $pattern = explode($delimiter, trim($this->routingTable['pattern'], $delimiter));
        foreach ($pattern as $k => $v) {
            if ($v[0] == $varprefix) {
                // 变量
                $varname = substr($v, 1);
                // 匹配变量
                if (isset($args[$varname])) {
                    $regex = "/^{$reqs[$varname]}\$/i";
                    if (preg_match($regex, $args[$varname])) {
                        $ret = str_replace($v, $args[$varname], $ret);
                        unset($args[$varname]);
                    }
                } else if (isset($default[$varname])) {
                    $ret = str_replace($v, $default[$varname], $ret);
                }
            } else if ($v[0] == '*') {
                // 通配符
                $tmp = '';
                foreach ($args as $key => $value) {
                    if (!isset($default[$key])) {
                        $tmp .= $key . $delimiter . rawurlencode($value) . $delimiter;
                    }
                }
                $tmp = rtrim($tmp, $delimiter);
                $ret = str_replace($v, $tmp, $ret);
                $ret = rtrim($ret, $delimiter);
            } else {
                // 静态
            }
        }
        if ('REWRITE' == $protocol) {
            $ret = $ret . $postfix;
        } else if ('PATH_INFO' == $protocol) {
            $ret = $_SERVER['SCRIPT_NAME'] . $delimiter . $ret . $postfix;
        } else {
            $ret = $ret . $postfix;
        }
        return $ret;
    }
}
